<?php

namespace app\common\model\merchant;


use app\common\loader\ModelMerchant;
use app\common\model\BaseModel;
use think\db\exception\DbException;
use think\Exception;
use yiqiniu\extend\facade\Logger;


/**
 * 商户充值记录
 * Class RechargeLog
 * @package app\common\model
 */
class RechargeLogModel extends BaseModel
{
    //
    protected $name = 'recharge_log';

    // 设置字段信息
    protected $schema = [
        'id' => 'int',        //
        'mer_id' => 'string',        // 店铺ID
        'pay_order' => 'string',        // 支付单号
        'pay_way' => 'int',        // 支付方式 1:线上支付   2:线下转帐 3:银行扫码
        'pay_money' => 'float',        // 支付金额
        'real_money' => 'float',        // 实际金额
        'pay_status' => 'int',        // 支付状态 0:未支付  1已支付
        'pay_time' => 'datetime',        // 支付时间
        'out_pay_order' => 'string',        // 外部支付单号
        'memo' => 'string',        // 备注
        'audit_mng_id' => 'int',        // 审核管理员
        'op_user' => 'int',        // 操作人
        'create_at' => 'datetime',        // 创建时间
        'update_at' => 'datetime',        // 更新时间
    ];

    /**
     * 添加支付记录
     * @param string $merID
     * @param int $payWay
     * @param float $money
     * @param int $opUser
     * @param string $memo
     * @return string
     * @throws Exception
     */
    public function addPayLog(string $merID, int $payWay, float $money, int $opUser, string $memo = ''): string
    {
        $payno = sprintf("%s-%s-%06d", make_unique_no('', 'm'), $merID, $money);
        $insertData = [
            'mer_id' => $merID,
            'pay_order' => $payno,
            'pay_way' => $payWay,
            'pay_money' => $money,
            'op_user' => $opUser,
            'pay_status' => 0,
            'create_at' => date('Y-m-d H:i:s')
        ];
        // 线下支付
        $this->db()->insert($insertData);
        return $insertData['pay_order'];
    }


    /**
     * 线下支付
     * @param string $payOrder
     * @param int $opUser
     * @param string $memo
     * @return bool
     * @throws Exception
     */
    public function offlinePay(string $payOrder, float $realMoney, int $opUser, string $memo)
    {
        if (empty($payOrder) || empty($opUser)) {
            throw new Exception('支付订单号和支付确认人不能为空', API_ERROR);
        }
        return $this->paySuccessHandler($payOrder, $realMoney, '', $opUser, $memo, PAY_METHOD_OFFLINE);
    }

    /**
     * 线上支付
     * @param string $pay_order 支付单号
     * @param string $out_pay_order 外部支付单号
     * @return bool
     * @throws Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function onlinePaySuccess(string $pay_order, string $out_pay_order): bool
    {
        if (empty($pay_order) || empty($out_pay_order)) {
            throw new Exception('支付订单号和外部流水号不能为空', API_ERROR);
        }
        return $this->paySuccessHandler($pay_order, 0, $out_pay_order, 0, '', PAY_METHOD_ONLINE);
    }

    /**
     * 支持成功的处理
     * @param string $pay_order 订单号
     * @param string $out_pay_order 外部支付单号  线上支付不能为空
     * @param int $pay_admin_id 支付用户
     * @param string $pay_memo 支付备注
     * @param int $pay_way 支付方式 1: 线上 2:线下
     * @return bool
     * @throws Exception
     */
    private function paySuccessHandler(string $pay_order,
                                       float  $realMoney,
                                       string $out_pay_order,
                                       int    $pay_admin_id,
                                       string $pay_memo,
                                       int    $pay_way = PAY_METHOD_ONLINE): bool
    {

        $pay_time = date('Y-m-d H:i:s');
        $payInfo = $this->db()->where('pay_order', $pay_order)->find();
        if (empty($payInfo)) {
            throw new Exception('支付信息未找到', API_ERROR);
        }
        // 该订单已被支付
        if ($payInfo['pay_status'] === 1) {
            throw new Exception('订单已支付', API_ERROR);
        }
        if ($payInfo['pay_status'] === 9) {
            throw new Exception('订单已取消', API_ERROR);
        }
        // 线下支付/ 余额支付
        if ($pay_way === PAY_METHOD_OFFLINE) {

            $payInfo['out_pay_order'] = '';
            $payInfo['real_money'] = $realMoney;
            $payInfo['pay_way'] = $pay_way;
            $payInfo['audit_mng_id'] = $pay_admin_id;
            $payInfo['memo'] = $pay_memo === '' ? '线下付款' : $pay_memo;

        } else {
            $payMoney = (float)$payInfo['pay_money'];
            // 线上充值，扣除手续费
            $payInfo['real_money'] = $payMoney - ($payMoney * RECHARGE_RATE);
            //线上支付
            $payInfo['out_pay_order'] = $out_pay_order;
        }
        $payInfo['update_at'] = $pay_time;
        $payInfo['pay_time'] = $pay_time;

        try {

            $this->startTrans();
            // 添加用户余额
            ModelMerchant::MerchantStock()->userBalanceEdit($payInfo['mer_id'], MONEY_CHANGE_ADD,
                $payInfo['real_money'], $pay_memo,
                $pay_admin_id, $pay_order, 1);
            // 更新订单信息
            $result = $this->updatePaySuccessOrder($payInfo);

            $this->commit();

        } catch (Exception $e) {
            $this->rollback();
            Logger::exception($e);
            $result = false;
        }
        if ($result) {
            // 处理支付成功
            event('PaySuccess', [
                    'mer_id' => $payInfo['mer_id'],
                    'pay_way' => $pay_way,
                    'pay_money' => $payInfo['pay_money'],
                    'pay_order' => $payInfo['pay_order'],
                ]
            );
        }
        return $result;
    }

    /**
     * 更新支付成功的订单信息
     * @param array $payinfo 订单信息
     * @return int
     * @throws \think\db\exception\DbException
     */
    private function updatePaySuccessOrder($payinfo)
    {
        $updateData = [
            'out_pay_order' => $payinfo['out_pay_order'] ?? '',
            'real_money' => $payinfo['real_money'],
            'pay_time' => $payinfo['pay_time'],
            'pay_way' => $payinfo['pay_way'],
            'pay_status' => 1,
            'memo' => $payinfo['memo'] ?? '',
            'audit_mng_id' => $payinfo['audit_mng_id'] ?? 0,
        ];
        return $this->db()->removeOption()
            ->where('pay_order', $payinfo['pay_order'])
            ->where('pay_status', 0)
            ->update($updateData);
    }

    /**
     * 查看充值记录
     * @param $where
     * @param $page_size
     * @return mixed
     * @throws \think\db\exception\DbException
     */
    public function pageList($where, $page_size)
    {
        return $this->db()->alias('a')->where($where)->order('id desc,create_at desc')
            ->paginate($page_size);
    }

    /**
     * 获取订单信息
     * @param string $pay_order
     * @return array
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getPayOrderInfo(string $pay_order)
    {
        return $this->db()->where('pay_order', $pay_order)
            ->withoutField('update_at,op_user,audit_mng_id,audit_time')
            ->find();
    }
    /**
     * 商户金额统计
     * @param $where
     * @return array
     * @throws DbException
     */
    public function rechargeMoneyList($where): array
    {
        return $this->db()->where($where)
            ->group('mer_id')
            ->column('sum(case when pay_status=1 then pay_money else 0 end) as pay_money'
                ,'mer_id');
    }

    /**
     * 一周内商户统计信息
     * @param array $option
     * @return array
     */
    public function rechargeMoneyNum($option)
    {
        return $this->db()
            ->group('mer_id')
            ->where($option ?? [])
            ->column('count(case when pay_status=1 then 1 else 0 end) as count','mer_id');
    }

    /**
     *  充值统计
     */
    public function getMerchantStatisticData($param)
    {
        $data = $this->db()->field('
                SUM(case when pay_status=1 then pay_money else 0 end) as pay_true_money,
                 SUM(case when pay_status=1 and pay_way=1 then pay_money else 0 end) as on_pay_money,
                 SUM(case when pay_status=1 and pay_way=2 then pay_money else 0 end) as below_pay_money,
                 SUM(case when pay_status=1 and pay_way=3 then pay_money else 0 end) as bank_pay_money
                ')
                ->where('mer_id' , '<>' ,'')
                ->where($param['log_where'])
                ->find() ?? [];
        $procedure_money = $data['on_pay_money'] * RECHARGE_RATE;
        return [
            'pay_true_money' => $data['pay_true_money'] ?? 0,
            'on_pay_money' => $data['on_pay_money'] ?? 0,
            'below_pay_money' => $data['below_pay_money'] ?? 0,
            'bank_pay_money' => $data['bank_pay_money'] ?? 0,
            'procedure_money' =>sprintf("%01.2f", $procedure_money ?? 0.00) ,

        ];

    }

}
